#!/sbin/openrc-run
#
# $Header: mkinitramfs-ll/svc/squashdir.initd            Exp $
# $Author: (c) 2012-6 tokiclover <tokiclover@gmail.com>  Exp $
# $License: 2-clause/new/simplified BSD                  Exp $
# $Version: 0.22.0 2016/07/20 12:33:03                   Exp $
#

description="Set up (AUFS|OverlayFS+SquashFS) union filesystems"

:	${NULL=/dev/null}
:	${sdr:=$(command -v sdr 2>${NULL})}
:	${squash_rootdir:=/squash}
case "${squash_filesystem}" in
	(aufs|overlay) ;;
	(*) squash_filesystem=;;
esac
mount="$(command -v mount 2>${NULL})"
umount="$(command -v umount 2>${NULL})"

depend()
{
	after localmount
	if [ "${RC_RUNLEVEL}" = "boot" ]; then
		before consolefont bootmisc acpid keymaps
	fi
}

start_pre()
{
	local mod
	ebegin "Setting up kernel modules"
	for mod in ${squash_filesystem:-aufs overlay} squashfs; do
		grep -q ${mod} /proc/filesystems || modprobe ${mod} >${NULL} 2>&1 ||
			case "${mod}" in
				(overlay|squashfs) { eend 1 ${mod}; return 1; };;
				(aufs) continue;;
			esac
		case "${mod}" in
			(aufs|overlay) squash_filesystem="${mod}"; break;;
		esac
	done
	eend ${?}
}

start()
{
	local dir
	for dir in ${squash_sysdir} ${squash_localdir}; do
		squash_mount "${squash_rootdir}" "${dir}"
	done
	return 0
}

stop()
{
	local dir
	for dir in ${squash_localdir}; do
		squash_umount "${squash_rootdir}" "${dir}"
	done
	for dir in ${squash_sysdir}; do
		squash_remount "${dir}" "ro"
	done
	return 0
}

stop_pre()
{
	local mod
	for mod in ${squash_filesystem:-aufs overlay}; do
		grep -q ${mod} /proc/filesystems &&
			{ squash_filesystem="${mod}"; break; }
	done
	[ -n "${squash_filesystem}"  ] || return
	[ -n "${squash_rebuild_dir}" ] || return 0
	[ -n "${sdr}" -a -x "${sdr}" ] || { ewarn "No suitable sdr found."; return; }

	ebegin "Rebuilding ${squash_rebuild_dir}"
	${sdr} -o${offset:-5} -f${squash_filesystem} ${squash_rebuild_dir} >${NULL} 2>&1
	eend ${?}
}

restart()
{
	stop
	start
	local dir
	for dir in ${squash_sysdir}; do
		squash_remount "${dir}" "rw"
	done
	return 0
}

squash_mount()
{
	local DIR message mnt_opts
	DIR="${1}/${2#/}" dir="/${2#/}"
	grep -qs ${squash_filesystem}:${dir} /proc/mounts && return
	[ -f ${DIR}.squashfs ] || return

	case "${squash_filesystem}" in
		(aufs)
			mkdir -p -m 0755 ${DIR}/rr ${DIR}/rw
			mnt_opts="nodev,udba=reval,br:${DIR}/rw:${DIR}/rr"
			message=AUFS;;
		(overlay)
			mkdir -p -m 0755 ${DIR}/rr ${DIR}/up ${DIR}/wk
			mnt_opts="nodev,upperdir=${DIR}/up,lowerdir=${DIR}/rr,workdir=${DIR}/wk"
			message=OverlayFS;;
	esac

	ebegin "Mounting ${squash_filesystem}:${dir}"
	if ! mountinfo -q ${DIR}/rr; then
		${mount} -t squashfs -o nodev,ro ${DIR}.squashfs ${DIR}/rr \
			>${NULL} 2>&1 || { eend 1 SquashFS; return 1; }
	fi
	${mount} -t ${squash_filesystem} -o ${mnt_opts} \
		${squash_filesystem}:${dir} ${dir} >${NULL} 2>&1
	eend "${?}" "${message}"
}

squash_umount()
{
	local DIR mnt_opts message
	DIR="${1}/${2#/}" dir="/${2#/}"
	grep -qs ${squash_filesystem}:${dir} /proc/mounts || return

	if [ "${RC_UNAME}" = "Linux" ]; then
		mnt_opts="-O no_netdev"
	fi
	case "${squash_filesystem}" in
		(aufs) auplink ${dir} flush >${NULL} 2>&1
			message=AUFS;;
		(*) message=OverlayFS;;
	esac
	ebegin "Umounting ${squash_filesystem}:${dir}"
	${umount} -l ${mnt_opts} ${squash_filesystem}:${dir} >${NULL} 2>&1 ||
		{ eend 1 ${message}; return 1; }
	${umount} -l ${mnt_opts} ${DIR}/rr   >${NULL} 2>&1
	eend "${?}" SquashFS
}

squash_remount()
{
	local message mnt_opts="${2:-ro}"
	dir="/${1#/}"
	if [ "${mnt_opts}" = "ro" ]; then
		message=read-only
	else
		message=read-write
	fi
	grep -qs ${squash_filesystem}:${dir} /proc/mounts || return
	ebegin "Remounting ${squash_filesystem}:${dir} (${message})"
	${mount} -o remount,${mnt_opts} ${squash_filesystem}:${dir} >${NULL} 2>&1
	eend "${?}"
}

#
# vim:fenc=utf-8:ft=gentoo-init-d:ci:pi:sts=0:sw=4:ts=4:
#
